home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Mud 4.0 / nlhack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-30  |  29.4 KB  |  1,246 lines  |  [TEXT/MPS ]

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #ifndef mac
  6. #include <time.h>
  7. #endif
  8. #include <math.h>
  9. #include <signal.h>
  10.  
  11. #include "config.h"
  12. #include "lint.h"
  13. #include "nlhack.h"
  14. #include "comm.h"
  15. #include "lang.h"
  16. #include "interpret.h"
  17. #include "wiz_list.h"
  18. #include "exec.h"
  19. #include "object.h"
  20. #include "rc.h"
  21.  
  22. #ifdef mac
  23. #include "mac.h"
  24.  
  25. struct tm *localtime(const time_t *timer);
  26. char *asctime (const struct tm *timeptr);
  27. #endif
  28.  
  29. #ifdef DIRENT
  30. #include <dirent.h>
  31. #define namlen(de) strlen((de)->d_name)
  32. #define direct dirent
  33. #else
  34. #include <sys/dir.h>
  35. #define namlen(de) (de)->d_namlen
  36. #endif
  37.  
  38. #ifdef MARK
  39. #include <prof.h>
  40. #endif
  41.  
  42. #ifdef MARK
  43. #define CASE(x) case x: MARK(x);
  44. #else
  45. #define CASE(x) case x:
  46. #endif
  47.  
  48. extern struct { unsigned counter, size; } sbrk_stat;
  49. extern struct object *master_ob;
  50. extern int num_player;
  51. extern struct interactive **all_players;
  52.  
  53. extern int fstat PROT((int, struct stat *));
  54. extern int stat PROT((char *, struct stat *));
  55.  
  56. extern void push_vector PROT((struct vector *));
  57. extern void push_svalue PROT((struct svalue *));
  58. extern void pop_n_elems PROT((int));
  59. extern int do_move PROT((char *, char *));
  60. extern struct variable *find_status PROT((char *, int));
  61. extern int get_line_number_if_any PROT((void));
  62. extern void show_info_about PROT((char *, char *, struct interactive *));
  63.  
  64. static struct vector *explode_file PROT((struct object *, char *));
  65. static int copy_file PROT((char *, char *));
  66. static int tail PROT((char *, int));
  67. static char *make_printable PROT((char *));
  68. static struct vector *list_files PROT((char *, char *, struct object *));
  69. static void full_name PROT((char *, int));
  70. static void fetch_type PROT((char *, char *, int));
  71. static int pstrcmp PROT((char **, char **));
  72. static int rename_file PROT((char *, char*));
  73. static int sroot PROT((int));
  74. static struct svalue *get_var PROT((char *));
  75. static int set_var PROT((char *, struct svalue *));
  76. static void grep PROT ((char *, struct vector *));
  77. static int write_file PROT((struct object *, char *, char *));
  78. static void people PROT((void));
  79. static void kick_me PROT((int));
  80. static int planet_shout PROT((struct object *, char *));
  81. static int match_illegal PROT((char *));
  82. static void set_hard_invis PROT((struct object *, int));
  83. static void set_see_hinvis PROT((struct object *, int));
  84.  
  85. void init_nlhack()
  86. {
  87. #ifdef _AIX
  88.     signal(SIGUSR1, kick_me);
  89. #endif
  90. }
  91.  
  92. static void kick_me(sig)
  93. int sig;
  94. {
  95. #ifndef mac
  96.     signal(SIGUSR1, kick_me);
  97. #endif
  98. }
  99.  
  100. int nlhack(instruction, pc, fp, sp, num_arg)
  101. int instruction, num_arg;
  102. char *pc;
  103. struct svalue *fp, *sp;
  104. {
  105.     int ret;
  106.     struct svalue *sval_ret;
  107.  
  108.     switch(instruction) {
  109.     default:
  110.         return 0;
  111.     CASE(F_GET_MEM_USAGE);
  112.         push_number(sbrk_stat.size);
  113.         break;
  114.     CASE(F_EXPLODE_FILE);
  115.     {
  116.         struct vector *v;
  117.         v = explode_file(current_object, sp->u.string);
  118.         pop_n_elems(1);
  119.         if (v) {
  120.         push_vector(v);
  121.         v->ref--;
  122.         }
  123.         else {
  124.         push_number(0);
  125.         }
  126.         break;
  127.     }
  128.     CASE(F_COPY_FILE);
  129.         ret = copy_file((sp-1)->u.string, sp->u.string);
  130.         pop_n_elems(2);
  131.         push_number(ret);
  132.         break;
  133.     CASE(F_TAIL);
  134.         if ((num_arg == 2 &&
  135.           ((sp-1)->type != T_NUMBER || sp->type != T_STRING)) ||
  136.           (num_arg == 1 && sp->type != T_STRING)) {
  137.         error("Bad type argument(s) to tail()\n");
  138.         }
  139.         if (num_arg == 2)
  140.         ret = tail(sp->u.string, (sp-1)->u.number);
  141.         else
  142.         ret = tail(sp->u.string, 20);
  143.         pop_n_elems(num_arg);
  144.         push_number(ret);
  145.         break;
  146.     CASE(F_LS);
  147.     {
  148.         struct vector *v;
  149.  
  150.         if (num_arg == 2)
  151.         v = list_files((sp-1)->u.string, sp->u.string, current_object);
  152.         else
  153.         v = list_files(sp->u.string,0, current_object);
  154.         pop_n_elems(num_arg);
  155.         if (v) {
  156.         push_vector(v);
  157.         v->ref--;
  158.         }
  159.         else {
  160.         push_number(0);
  161.         }
  162.         break;
  163.     }
  164.     CASE(F_RENAME_FILE);
  165.         ret = rename_file((sp-1)->u.string, sp->u.string);
  166.         pop_n_elems(2);
  167.         push_number(ret);
  168.         break;
  169.     CASE(F_SQRT);
  170.         ret = sroot(sp->u.number);
  171.         pop_n_elems(1);
  172.         push_number(ret);
  173.         break;
  174.     CASE(F_GET_VAR);
  175.         sval_ret = get_var(sp->u.string);
  176.         pop_n_elems(1);
  177.         if (sval_ret)
  178.         push_svalue(sval_ret);
  179.         else
  180.         push_number(0);
  181.         break;
  182.     CASE(F_SET_VAR);
  183.         ret = set_var((sp-1)->u.string, sp);
  184.         pop_n_elems(2);
  185.         push_number(ret);
  186.         break;
  187.     CASE(F_GREP);
  188.         grep((sp-1)->u.string, sp->u.vec);
  189.         pop_n_elems(2);
  190.         push_number(0);
  191.         break;
  192.     CASE(F_WRITE_FILE);
  193.         ret = write_file(current_object, (sp-1)->u.string, sp->u.string);
  194.         pop_n_elems(2);
  195.         push_number(ret);
  196.         break;
  197.     CASE(F_PEOPLE);
  198.         people();
  199.         break;
  200.     CASE(F_PLANET_SHOUT);
  201.         ret = planet_shout((sp-1)->u.ob, sp->u.string);
  202.         pop_n_elems(2);
  203.         push_number(ret);
  204.         break;
  205.     CASE(F_SET_HARD_INVIS);
  206.         set_hard_invis((sp-1)->u.ob, sp->u.number);
  207.         pop_n_elems(2);
  208.         push_number(0);
  209.         break;
  210.     CASE(F_SET_SEE_HINVIS);
  211.         set_see_hinvis((sp-1)->u.ob, sp->u.number);
  212.         pop_n_elems(2);
  213.         push_number(0);
  214.         break;
  215.     }
  216.     return 1;
  217. }
  218.  
  219. static struct vector *explode_file(ob, fname)
  220.     char *fname;
  221.     struct object *ob;
  222. {
  223.    char line[1000], what[100];
  224.    struct vector *ret;
  225.    FILE *f;
  226.    int lines = 0, i = 0;
  227.  
  228.     if (!fname)
  229.        return 0;
  230.     if (fname[0] == '/') fname++;
  231. #ifdef COMPAT_MODE
  232.     if (ob->user) {
  233.     if (strncmp(fname, "players/", 8) != 0 ||
  234.         strncmp(fname+8, ob->user->name, strlen(ob->user->name)) != 0 ||
  235.         !legal_path(fname))
  236.         {
  237.         error("Illegal use of explode_file(%s)\n", fname);
  238.         return 0;
  239.     }
  240.     } else if ((strncmp(ob->name, "obj/", 4) != 0  && 
  241.     strncmp(ob->name, "room/", 5) != 0) ||
  242.     !legal_path(fname)) {
  243.            error("Illegal use of explode_file(%s)\n", fname);
  244.            return 0;
  245.     }
  246.     if (ob != master_ob && sscanf(fname, "log/admin/%s", what) == 1)
  247.     return 0;
  248. #else
  249.     fname = check_valid_path(fname, ob->eff_user, "explode_file", 0);
  250.     if (!fname)
  251.     return 0;
  252. #endif
  253.     f = fopen(fname, "r");
  254.     if (f == 0)
  255.     return 0;
  256.     while (fgets(line, sizeof line, f) != 0)
  257.        lines++;
  258.     if (lines == 0) 
  259.     { 
  260.        fclose(f);
  261.        return 0;
  262.     }
  263.     if (lines > MAX_EXPLODE_FILE_LINES) lines = MAX_EXPLODE_FILE_LINES;
  264.     ret = allocate_array(lines);
  265.     rewind(f);
  266.     while (i != lines && fgets(line, sizeof line, f) != 0)
  267.     {
  268.     if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0';
  269.     ret->item[i].type  = T_STRING;
  270.     ret->item[i].string_type  = STRING_MALLOC;
  271.     ret->item[i].u.string = string_copy(line); 
  272.     i++;
  273.     }
  274.     fclose(f);
  275.     return ret;
  276. }
  277.  
  278. static int copy_file(source, dest)
  279.    char *source, *dest;
  280. {
  281.    char src[512], *dst;
  282.    char line[1000];
  283.    FILE *sf, *df;
  284.  
  285. #ifdef COMPAT_MODE
  286.     if (command_giver->name != current_object->name)
  287.     {
  288.     /*
  289.      * Security patch.
  290.      */
  291.     add_message("Illegal use of copy_file.\n");
  292.     return 0;
  293.     }
  294.     source = check_file_name(source , 0);
  295. #else
  296.     source = check_valid_path(source, current_object->eff_user, "copy_file", 0);
  297. #endif
  298.     if (source == 0)
  299.         return 0;
  300.     /*
  301.      * The next part is necessary, because the return string of check_file_name
  302.      * might be deallocated at the next "apply" (which is called from
  303.      * check_file_name itself, used again below).
  304.      */
  305.     strncpy(src, source, sizeof src);
  306.     src[sizeof src - 1] = '\0';
  307. #ifdef COMPAT_MODE
  308.     dst = check_file_name(dest, 1);
  309. #else
  310.     dst = check_valid_path(dest, current_object->eff_user, "copy_file", 1);
  311. #endif
  312.     if (dst == 0)
  313.        return 0;
  314.     sf = fopen(src, "r");
  315.     if (sf == 0)
  316.        return 0;
  317. #if defined(LOG_OPEN) && defined(COMPAT_MODE)
  318.     if (strncmp(dst, "open/", 5) == 0) {
  319.     FILE *fp;
  320.     fp = fopen("log/admin/OPEN", "a");
  321.     if (fp != NULL) {
  322.         fprintf(fp, "\"%s\" by %s\n",
  323.           dst,
  324.           command_giver->living_name);
  325.         fclose(fp);
  326.     }
  327.     }
  328. #endif
  329.     df = fopen(dst, "w");
  330.     if (df == 0)
  331.     {
  332.     fclose(sf);
  333.     return 0;
  334.     }
  335.     while (fgets(line, sizeof line, sf) != 0)
  336.         fputs(line, df);
  337.     fclose(sf);
  338.     fclose(df);
  339.     return 1;
  340. }
  341.  
  342. static int tail(path, start)
  343.     char *path;
  344.     int start;
  345. {
  346.     char buff[1000];
  347.     FILE *f;
  348.     struct stat st;
  349.     int offset;
  350.  
  351.     if (start < 1) return 0;
  352.     if (start > 5 * MAX_LINES) start = 5 * MAX_LINES;
  353. #ifdef COMPAT_MODE
  354.     path = check_file_name(path, 0);
  355. #else
  356.     path = check_valid_path(path, current_object->eff_user, "tail", 0);
  357. #endif
  358.     if (path == 0)
  359.         return 0;
  360.     f = fopen(path, "r");
  361.     if (f == 0)
  362.     return 0;
  363.     if (fstat(fileno(f), &st) == -1)
  364.     fatal("Could not stat an open file.\n");
  365.     offset = st.st_size - 80 * start;
  366.     if (offset < 0)
  367.     offset = 0;
  368.     if (fseek(f, offset, 0) == -1)
  369.     fatal("Could not seek.\n");
  370.     /* Throw away the first incomplete line. */
  371.     if (offset > 0)
  372.     (void)fgets(buff, sizeof buff, f);
  373.     while(fgets(buff, sizeof buff, f)) {
  374.     add_message("%s", make_printable(buff));
  375.     }
  376.     fclose(f);
  377.     return 1;
  378. }
  379.  
  380. static char *make_printable(s)
  381. register char *s;
  382. {
  383.     static char buff[2000];
  384.     register char *p;
  385.  
  386.     p = buff;
  387.     while (*s) {
  388.     if (*s < ' ' && *s != '\t' && *s != '\n') {
  389.         *p++ = '^';
  390.         *p++ = '@' + (*s & 0x2f);
  391.     } else {
  392.         *p++ = *s;
  393.     }
  394.     s++;
  395.     }
  396.     *p = '\0';
  397.     return buff;
  398. }
  399.  
  400. static void full_name(name, n)
  401.    char name[];
  402.    int n;
  403. {
  404.    int i;
  405.    if (strlen(name) < n)
  406.        for (i = strlen(name); i < n; i++) name[i] = ' ';
  407.    name[n] = '\0';
  408. }
  409.  
  410. static void fetch_type(path, file, L_opt)
  411.     char path[], file[];
  412.     int L_opt;
  413. {
  414.     char temp[100];
  415.     struct stat st;
  416.  
  417.     (void)strcpy(temp, path);
  418.     (void)strcat(temp, "/");
  419.     (void)strcat(temp, file);
  420.     if (stat(temp, &st) == -1) return;
  421.     if (S_ISDIR(st.st_mode)) (void)strcat(file, "/");
  422.     else {
  423.     if (file[strlen(file)-1] == 'c' && file[strlen(file)-2] == '.') {
  424.         if (L_opt) {
  425.         if (find_object2(temp))
  426.             strcat(file, "@");
  427.         }
  428.         else {
  429.         (void)strcat(file, "*");
  430.         }
  431.     }
  432.     }
  433. }
  434.  
  435. static int pstrcmp(p1, p2)
  436.     char **p1, **p2;
  437. {
  438.     return strcmp(*p1, *p2);
  439. }
  440.  
  441. static int rename_file(fr, t)
  442.    char *fr, *t;
  443. {
  444.     char from[512], *to;
  445.     struct stat st;
  446.  
  447. #ifdef COMPAT_MODE
  448.     if (command_giver->name != current_object->name)
  449.     {
  450.     /*
  451.      * Security patch.
  452.      */
  453.     add_message("Illegal use of rename_file.\n");
  454.     return 0;
  455.     }
  456.     fr = check_file_name(fr, 1);
  457. #else
  458.     fr = check_valid_path(fr, current_object->eff_user, "rename_file", 1);
  459. #endif
  460.     if (fr == 0)
  461.         return 0;
  462.     strncpy(from, fr, sizeof from);
  463.     from[sizeof from - 1] = '\0';
  464. #ifdef COMPAT_MODE
  465.     to = check_file_name(t, 1);
  466. #else
  467.     to = check_valid_path(t, current_object->eff_user, "rename_file", 1);
  468. #endif
  469.     if (to == 0)
  470.         return 0;
  471. #ifdef LOG_OPEN
  472.     if (strncmp(to, "open/", 5) == 0) {
  473.     FILE *fp;
  474.     fp = fopen("log/admin/OPEN", "a");
  475.     if (fp != NULL) {
  476.         fprintf(fp, "\"%s\" by %s\n",
  477.           to,
  478.           command_giver->living_name);
  479.         fclose(fp);
  480.     }
  481.     }
  482. #endif
  483.     /*
  484.      * This now calls do_move from simulate.c, which handles cross-filesystem
  485.      * moves.
  486.      */
  487.     if (stat(from, &st) < 0)
  488.     return 0;
  489.     return !do_move(from, to);
  490. }
  491.  
  492. static int sroot(n)
  493.    int n;
  494. {
  495.    return n < 0 ? -1 : (int) sqrt((double) n);
  496. }
  497.  
  498. static struct svalue *get_var(str)
  499. char *str;
  500. {
  501.     struct variable *p;
  502.  
  503.     p = find_status(str, 0);
  504.     if (!p)
  505.     return 0;
  506.     return ¤t_object->variables[p - current_object->prog->variable_names];
  507. }
  508.  
  509. static int set_var(str, arg1)
  510. char *str;
  511. struct svalue *arg1;
  512. {
  513.     struct variable *p;
  514.  
  515.     p = find_status(str, 0);
  516.     if (!p)
  517.     return 0;
  518.     assign_svalue(
  519.     ¤t_object->variables[p - current_object->prog->variable_names],
  520.         arg1);
  521.     return 1;
  522. }
  523.  
  524. static void grep(str, files)
  525.     char *str;
  526.     struct vector *files;
  527. {
  528.     char temp[500], command[750], line[1000], *t;
  529.     int i, a, nr_lines = 0, nr_files = 0;
  530.     struct stat st;
  531.     FILE *f;
  532.  
  533.     if (!str || !(files->size) || files->item[0].type != T_STRING)
  534.        return;
  535.     if (current_object != command_giver)
  536.     {
  537.        add_message("Illegal use of grep()\n");
  538.        return;
  539.     }
  540.     for (i = 0; i < files->size; i++)
  541.        if (files->item[i].type == T_STRING)
  542.        {
  543. #ifdef COMPAT_MODE
  544.       t = check_file_name(files->item[i].u.string, 0);
  545. #else
  546.       t = check_valid_path(files->item[i].u.string,
  547.         current_object->eff_user,"grep", 0);
  548. #endif
  549.       if (t && stat(t, &st) != -1)
  550.       {
  551.          if (st.st_size <= GREP_FILE_SIZE) 
  552.          {
  553.                 (void)strcpy(temp, t);
  554.             nr_files++;
  555.             break;
  556.              }
  557.          else
  558.         add_message("%s : Too big.\n", t);
  559.           }
  560.        }
  561.     if (!nr_files)
  562.     {
  563.        add_message("No or illegal file(s)!\n");
  564.        return;
  565.     }
  566.     for (a = i+1; a < files->size; a++) 
  567.     {
  568.        if (nr_files >= MAX_GREP_SIZE)
  569.        {
  570.        add_message("Too many grep files! Working on %d files now.\n", MAX_GREP_SIZE);
  571.        break;
  572.        }
  573.        if (files->item[a].type == T_STRING)
  574.        {
  575.       t = check_file_name(files->item[a].u.string, 0);
  576.       if (t && stat(t, &st) != -1)
  577.       {
  578.          if (st.st_size <= GREP_FILE_SIZE)
  579.          {
  580.                 (void)strcat(temp, " ");
  581.             (void)strcat(temp, t); 
  582.             nr_files++;
  583.              }
  584.          else
  585.         add_message("%s : Too big.\n", t);
  586.           }
  587.        }
  588.        else
  589.       error("Corrupted file-array!\n");
  590.     }
  591.     (void)sprintf(command, "fgrep -n %s %s > %s", str, temp, GREP_FILE);
  592.     (void)system(command);
  593.     f = fopen(GREP_FILE, "r");
  594.     if (!f)
  595.     {
  596.     add_message("No match.\n");
  597.     return;
  598.     }
  599.     while(fgets(line, sizeof line, f) != 0)
  600.     {
  601.     add_message("%s", line);
  602.     nr_lines++;
  603.     if (nr_lines > MAX_LINES)
  604.     {
  605.        add_message("**TRUNCATED**\n");
  606.        break;
  607.         }
  608.     }
  609.     fclose(f);
  610.     unlink(GREP_FILE);
  611. }
  612.  
  613. static int write_file(ob, file, str)
  614.     char *file;
  615.     char *str;
  616.     struct object *ob;
  617. {
  618.     FILE *f;
  619.     char what[100];
  620.  
  621.     if (!file)
  622.     return 0;
  623.     if (file[0] == '/') file++; 
  624. #ifdef COMPAT_MODE
  625.     if (ob->user) {
  626.     if (strncmp(file, "players/", 8) != 0 ||
  627.         strncmp(file+8, ob->user->name, strlen(ob->user->name)) != 0 ||
  628.         !legal_path(file)) {
  629.         error("Illegal write_file(%s)\n", file);
  630.     }
  631.     } else if ((strncmp(current_object->name, "obj/", 4) != 0 &&
  632.     strncmp(current_object->name, "room/", 5) != 0 &&
  633.     strncmp(current_object->name, "std/", 4) != 0) ||
  634.     !legal_path(file)) {
  635.     error("Illegal use of write_file()\n");
  636.     }
  637.     if (sscanf(file, "users/%s", what) == 1)
  638.        if (!strchr(what, '/')) error("Illegal use of write_file()\n");
  639.     if (sscanf(file, "obj/%s", what) == 1)
  640.        error("Illegal use of write_file()\n");
  641. #else
  642.     file = check_valid_path(file, current_object->eff_user, "write_file", 1);
  643. #endif
  644.     f = fopen(file, "a");
  645.     if (f == 0)
  646.     return 0;
  647.     fwrite(str, strlen(str), 1, f);
  648.     fclose(f);
  649.     return 1;
  650. }
  651.  
  652. struct vector *users() {
  653.     static struct object **tmp_arr = 0;
  654.     int i, vis, n, invis;
  655.     struct vector *ret;
  656.  
  657.     if (!tmp_arr)
  658.     tmp_arr = (struct object **)
  659.         xalloc(MAX_PLAYERS * sizeof (struct object *));
  660.     invis = !command_giver || !(command_giver->flags & O_CAN_SEE_HINVIS);
  661.     for (i = 0, n = num_player, vis = 0; n; i++) {
  662.     if (all_players[i]) {
  663.         n--;
  664.         if (!(invis && (all_players[i]->ob->flags & O_HARD_INVIS)))
  665.         tmp_arr[vis++] = all_players[i]->ob;
  666.     }
  667.     }
  668.     ret = allocate_array(vis);
  669.     for (i = 0; i < vis; i++) {
  670.     ret->item[i].type = T_OBJECT;
  671.     ret->item[i].u.ob = tmp_arr[i];
  672.     add_ref(tmp_arr[i], "users");
  673.     }
  674.     return ret;
  675. }
  676.  
  677. /* Returns an array of all objects contained in 'ob'
  678.  */
  679. struct vector *all_inventory(ob)
  680.     struct object *ob;
  681. {
  682.     struct vector *d;
  683.     struct object *cur;
  684.     int cnt, invis;
  685.  
  686.     invis = !command_giver || !(command_giver->flags & O_CAN_SEE_HINVIS);
  687.     for (cnt=0, cur=ob->contains; cur; cur = cur->next_inv) {
  688.     if (invis && (cur->flags & O_HARD_INVIS))
  689.         continue;
  690.     else
  691.         cnt++;
  692.     }
  693.     if (!cnt)
  694.     return allocate_array(0);
  695.  
  696.     d = allocate_array(cnt);
  697.     for (cnt=0, cur=ob->contains; cur; cur = cur->next_inv) {
  698.     if (invis && (cur->flags & O_HARD_INVIS))
  699.         continue;
  700.     d->item[cnt].type=T_OBJECT;
  701.     d->item[cnt].u.ob = cur;
  702.     add_ref(cur,"all_inventory");
  703.     cnt++;
  704.     }
  705.     return d;
  706. }
  707.  
  708. static void people()
  709. {
  710.     struct object *ob;
  711.     struct svalue *player;
  712.     int n, i, invis;
  713.  
  714.     invis = !command_giver || !(command_giver->flags & O_CAN_SEE_HINVIS);
  715.     for (i = 0, n = num_player; n; i++) {
  716.     if (!all_players[i])
  717.         continue;
  718.     n--;
  719.     ob = all_players[i]->ob;
  720.     if (invis && (ob->flags & O_HARD_INVIS))
  721.         continue;
  722.     player = apply("query_name", ob, 0);
  723.     if (player == 0 || player->type != T_STRING)
  724.         continue;
  725.     if (!ob->super)
  726.         continue;
  727.     show_info_about(player->u.string, ob->super->name, ob->interactive);
  728.     }
  729. }
  730.  
  731. void set_eff_user(new_ob)
  732. struct object *new_ob;
  733. {
  734.     /*
  735.      * Dirty hack made a lot dirtier: since I did not want to add another
  736.      * field to the object struct, I abused the eff_user field, which is not
  737.      * used in COMPAT_MODE. This hack is _incompatible_ with 'native' mode.
  738.      * - Zappa
  739.      */
  740.     if (current_object) {
  741.     if (current_object->interactive && current_object->living_name) {
  742.         new_ob->eff_user = (struct wiz_list *)
  743.         make_shared_string(current_object->living_name);
  744.     } else {
  745.         new_ob->eff_user = current_object->eff_user;
  746.     }
  747.     }
  748.     else {
  749.     new_ob->eff_user = 0;
  750.     }
  751. }
  752.  
  753. /*
  754.  * List files in a directory. The standard 'ls' could be used, but
  755.  * it takes too much time.
  756.  * Prepared for flag decoding.
  757.  *
  758.  * Look at the the last component of the path name. It is a regular
  759.  * expression, select only matching files.
  760.  *
  761.  * All .i files are only listed if they match the regexp.
  762.  */
  763. static struct vector *list_files(path, flags, ob)
  764.     char *path, *flags;
  765.     struct object *ob;
  766. {
  767.     char buff[160];    /* Will never need more than two lines */
  768.     int i, max, lines, num, j, truncated = 0, pos;
  769.     DIR *dirp;
  770.     struct direct *de;
  771.     char **names, name_buffer[MAX_LINES * 80];
  772.     struct stat st;
  773.     char regexp[80], *p, path2[100], temp[100], temp2[10];
  774.     int do_match = 0, all = 0, long_list = 0, f_opt = 0, to_array = 0;
  775.     int L_opt = 0;
  776.     struct vector *ret;
  777.  
  778.     if (!path)
  779.         path = ".";
  780. #ifdef COMPAT_MODE
  781.     path = check_file_name(path, 0);
  782. #else
  783.     path = check_valid_path(path, current_object->eff_user, "ls", 0);
  784. #endif
  785.     if (path == 0)
  786.         return 0;
  787.     if (flags)
  788.     {
  789.        for (i=0; i < strlen(flags); i++)
  790.       if (flags[i] != 'a' && flags[i] != 'l' && 
  791.           flags[i] != 'F' && flags[i] != '@' &&
  792.           flags[i] != 'L') return 0;
  793.     if (strchr(flags, 'a')) all = 1;
  794.     if (strchr(flags, 'l')) long_list = 1;
  795.     if (strchr(flags, 'F')) f_opt = 1;
  796.     if (strchr(flags, '@')) to_array = 1;
  797.     if (strchr(flags, 'L')) L_opt = 1;
  798.     }
  799.     if (to_array)  /* to maintain security */
  800.     {
  801.        if (ob->user) {
  802.        if (strncmp(path, "players/", 8) != 0 ||
  803.            strncmp(path+8, ob->user->name, strlen(ob->user->name)) != 0 ||
  804.            !legal_path(path))
  805.            {
  806.            error("Illegal use of ls(%s)\n", path);
  807.            return 0;
  808.        }
  809.        } else if ((strncmp(current_object->name, "obj/", 4) != 0  && 
  810.        strncmp(current_object->name, "room/", 5) != 0 &&
  811.        strncmp(current_object->name, "std/", 4) != 0) ||
  812.        !legal_path(path)) {
  813.               error("Illegal use of ls()\n");
  814.               return 0;
  815.        }
  816.     }
  817.     strncpy(path2, path, sizeof path2);
  818.     path2[sizeof path2 - 1] = '\0';
  819.     p = path2 + strlen(path2) - 2;
  820.     if (p >= path2 && p[0] == '/' && p[1] == '.')
  821.     p[0] = '\0';
  822.     if (stat(path2, &st) == -1) {
  823.     /* Either the directory does not exist, or it is a regexp
  824.      * file name. Strip of the last component.
  825.      */
  826.     p = strrchr(path2, '/');
  827.     if (p == 0 || p[1] == '\0')
  828.         return 0;
  829.     strncpy(regexp, p+1, sizeof regexp);
  830.     regexp[sizeof regexp - 1] = '\0';
  831.     *p = '\0';
  832.     do_match = 1;
  833.     }
  834.     dirp = opendir(path2);
  835.     if (dirp == 0) {
  836.     add_message("No such directory '%s'\n", path2);
  837.     return 0;
  838.     }
  839.     pos = 0;
  840.     max = 0;
  841.     num = 0;
  842.     /*
  843.      * First step, find the number of file names.
  844.      */
  845.     for(de = readdir(dirp); de; de = readdir(dirp)) {
  846.     if (!do_match && de->d_name[namlen(de)-1] == 'i' &&
  847.         de->d_name[namlen(de)-2] == '.')
  848.         continue;
  849.     if ((strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0))
  850.         continue;
  851.     if (do_match && !match_string(regexp, de->d_name))
  852.         continue;
  853.         if (!all && (!do_match || strcmp(regexp, "*") == 0) 
  854.        && de->d_name[0] == '.')
  855.         continue;
  856.     if (namlen(de) + pos >= sizeof name_buffer) {
  857.         truncated = 1;
  858.         break;
  859.     }
  860.     if (namlen(de) > max)
  861.         max = namlen(de) + 1;
  862.     pos += namlen(de) + 1;
  863.     num++;
  864.     }
  865.     if (num == 0)
  866.     {
  867.     closedir(dirp);
  868.     return 0;
  869.     }
  870.     max++;
  871.     /*
  872.      * Copy all file names into a name space, and set up pointer
  873.      * into it.
  874.      */
  875.     names = (char **)alloca(num * sizeof (char *));
  876.     rewinddir(dirp);
  877.     for(pos=0, i=0, de = readdir(dirp); i < num; de = readdir(dirp)) {
  878.     if (!do_match && de->d_name[namlen(de)-1] == 'i' &&
  879.         de->d_name[namlen(de)-2] == '.')
  880.         continue;
  881.     if ((strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0))
  882.         continue;
  883.     if (do_match && !match_string(regexp, de->d_name))
  884.         continue;
  885.         if (!all && (!do_match || strcmp(regexp, "*") == 0) 
  886.        && de->d_name[0] == '.')
  887.         continue;
  888.     names[i] = name_buffer + pos;
  889.     if (f_opt || L_opt)
  890.     {
  891.         (void)strcpy(temp, de->d_name);
  892.         fetch_type(path2, temp, L_opt);
  893.         strcpy(name_buffer + pos, temp);
  894.         pos += strlen(temp) + 1;
  895.         }
  896.     else
  897.     {
  898.         strcpy(name_buffer + pos, de->d_name);
  899.         pos += namlen(de) + 1;
  900.         }
  901.     i++;
  902.     }
  903.     /* Sort the names. */
  904.     qsort((char *)names, num, sizeof (char *), pstrcmp);
  905.     /*
  906.      * Print the file names in nice columns, as many as possible
  907.      * on every line. That means that there can be one extra name
  908.      * on each line, depending on the size of the last name on the line.
  909.      */
  910.     if (!long_list)
  911.     {
  912.        if (to_array)
  913.        /*
  914.     * got to determine array-size
  915.     */
  916.        {
  917.            for(lines=0, i=0, j=0; j<num; j++) {
  918.               if (i * max + strlen(names[j]) >= 79) {
  919.                     i = 0;
  920.               lines++;
  921.               if (lines > MAX_LINES) break; 
  922.            }
  923.            i++;
  924.            }
  925.        ret = allocate_array(lines+1);
  926.        }
  927.        for(lines=0, i=0, j=0; j<num; j++) {
  928.           if (i * max + strlen(names[j]) >= 79) {
  929.         /*
  930.          * Strip the last spaces on the last name to ensure that
  931.          * it will fit last on the line.
  932.          */
  933.            for (i=strlen(buff) - 1; buff[i] == ' '; i--)
  934.               buff[i] = '\0';
  935.                if (!to_array)
  936.               add_message("%s\n", buff);
  937.                else
  938.            {
  939.           (void) strcpy(temp, buff); 
  940.           ret->item[lines].type = T_STRING;
  941.           ret->item[lines].string_type = STRING_MALLOC;
  942.           ret->item[lines].u.string = string_copy(strcat(temp, "\n")); 
  943.                }
  944.            i = 0;
  945.            lines++;
  946.            if (lines > MAX_LINES) {
  947.               truncated = 1;
  948.            break;
  949.            }
  950.        }
  951.        sprintf(buff + i * max, "%-*s", max, names[j]);
  952.        i++;
  953.        }
  954.        if (i)
  955.        {
  956.       if (!to_array)
  957.             add_message("%s\n", buff);
  958.           else
  959.       {
  960.          (void) strcpy(temp, buff); 
  961.          ret->item[lines].type = T_STRING;
  962.          ret->item[lines].string_type = STRING_MALLOC;
  963.          ret->item[lines].u.string = string_copy(strcat(temp, "\n")); 
  964.              lines++;
  965.           }
  966.        }
  967.     }
  968.     else
  969.     {
  970.        char owner[15];
  971.  
  972.        if (to_array)
  973.       if (num <= MAX_LINES)
  974.          ret = allocate_array(num);
  975.           else
  976.          ret = allocate_array(MAX_LINES + 2);
  977.        if (sscanf(path2, "players/%s", owner) != 1)
  978.        {
  979.           if (sscanf(path2, "open/%s", owner) != 0)
  980.          (void)strcpy(owner, "open\0");
  981.       else 
  982.          (void)strcpy(owner, "system\0");
  983.        }
  984.        else 
  985.        {
  986.       p = strchr(owner, '/');
  987.       if (p) *p = '\0';
  988.        }
  989.        full_name(owner, 12);
  990.        (void)strcat(path2, "/");
  991.        for(lines=0, j=0; j<num; j++) {
  992.        int len;
  993.  
  994.        (void)strcpy(temp, path2);
  995.        (void)strcat(temp, names[j]);
  996.        if (L_opt || f_opt) {
  997.         len = strlen(temp) - 1;
  998.         if (strchr("*@/", temp[len]))
  999.             temp[len] = '\0';
  1000.        }
  1001.        if (stat(temp, &st) == -1) continue;
  1002.            (void)strcpy(temp, names[j]);
  1003.            full_name(temp, 20);
  1004.        (void)strcat(temp,"----> ");
  1005.        if (S_ISDIR(st.st_mode))
  1006.           (void)strcat(temp, "Directory\t");
  1007.            else
  1008.           (void)strcat(temp, "File\t\t");
  1009.        sprintf(temp2, "%d", st.st_size);
  1010.        (void)strcat(temp, temp2);
  1011.        (void)strcat(temp, "\t");
  1012.            (void)strcat(temp, owner);
  1013. #ifdef NOSTRFTIME
  1014.        strcpy(buff, asctime(localtime(&(st.st_mtime))) + 4);
  1015.        buff[12] = '\0';
  1016. #else
  1017.        strftime(buff, 100, "%h %d %H:%M", localtime(&(st.st_mtime)));
  1018. #endif
  1019.            (void)strcat(temp, buff);
  1020.        if (!to_array)
  1021.           add_message("%s\n", temp);
  1022.            else
  1023.        {
  1024.           (void) strcpy(buff, temp);
  1025.           ret->item[lines].type = T_STRING;
  1026.           ret->item[lines].string_type = STRING_MALLOC;
  1027.           ret->item[lines].u.string = string_copy(strcat(buff, "\n"));
  1028.            }
  1029.            lines++;
  1030.            if (lines > MAX_LINES) {
  1031.               truncated = 1;
  1032.           break;
  1033.        }
  1034.        }
  1035.     }
  1036.     if (truncated)
  1037.        if (!to_array)
  1038.       add_message("***TRUNCATED***\n");
  1039.        else {
  1040.       ret->item[lines].type = T_STRING;
  1041.       ret->item[lines].string_type = STRING_MALLOC;
  1042.       ret->item[lines].u.string = string_copy("***TRUNCATED***\n");
  1043.     }
  1044.     closedir(dirp);
  1045.     return (to_array) ? ret : 0;
  1046. }
  1047.  
  1048. static int planet_shout(planet, mess)
  1049.     struct object *planet;
  1050.     char *mess;
  1051. {
  1052.     struct object *ob, *save_command_giver = command_giver;
  1053.     char *p;
  1054.     struct svalue *muffled, *cur_planet;
  1055.     int nr = 0, i, n;
  1056.  
  1057.     for (p=mess; *p; p++) {
  1058.     if ((*p < ' ' || *p > '~') && *p != '\n')
  1059.         *p = ' ';
  1060.     }
  1061.     p = 0;
  1062.     /*
  1063.      * This should be in simul_efun.c..
  1064.      */
  1065.     for (i = 0, n = num_player; n; i++)
  1066.     {
  1067.     if (!all_players[i])
  1068.         continue;
  1069.     n--;
  1070.     ob = all_players[i]->ob;
  1071.     if (ob == save_command_giver)
  1072.         continue;
  1073.         muffled = apply("query_muffled", ob, 0);
  1074.     if (muffled && muffled->type == T_NUMBER && muffled->u.number == 1)
  1075.         continue;
  1076.         cur_planet = apply("query_planet_obj", ob, 0);
  1077.     if (!cur_planet || cur_planet->type != T_OBJECT ||
  1078.         cur_planet->u.ob != planet) 
  1079.            continue;
  1080.         nr++;
  1081.     command_giver = ob;
  1082.     add_message("%s", mess);
  1083.     }
  1084.     command_giver = save_command_giver;
  1085.     return nr;
  1086. }
  1087.  
  1088. void log_sbrk(size)
  1089. unsigned size;
  1090. {
  1091.     int lineno;
  1092.  
  1093.     lineno = get_line_number_if_any();
  1094.     if (current_object) {
  1095.     printf("sbrk(%d) object: '%s'", size, current_object->name);
  1096.     if (lineno)
  1097.         printf(", program: '%s' line %d\n", current_prog->name, lineno);
  1098.     else
  1099.         putchar('\n');
  1100.     }
  1101. }
  1102.  
  1103. char **log_admin_files;
  1104. int nr_log_admin_files;
  1105.  
  1106. int log_admin_check(file)
  1107. char *file;
  1108. {
  1109.     int i;
  1110.  
  1111.     for (i = 0; i < nr_log_admin_files; i++)
  1112.     if (!strcmp(file, log_admin_files[i]))
  1113.         return 1;
  1114.     return 0;
  1115. }
  1116.  
  1117. int remove_file(path)
  1118.     char *path;
  1119. {
  1120.     DIR *dirp;
  1121.     struct direct *de;
  1122.     struct stat st;
  1123.     char rgexp[100], *p, path2[200], temp[200];
  1124.     int do_match = 0, danger = 0, found = 0, interactive;
  1125.  
  1126. #ifdef COMPAT_MODE
  1127.     path = check_file_name(path, 1);
  1128. #else
  1129.     path = check_valid_path(path, current_object->eff_user, "remove_file", 1);
  1130. #endif
  1131.  
  1132.     if (path == 0)
  1133.         return 0;
  1134.     /*
  1135.      * Wildcards may only be used from player.c
  1136.      */
  1137.     interactive = (command_giver && command_giver == current_object);
  1138.     strncpy(path2, path, sizeof path2);
  1139.     path2[sizeof path2 - 1] = '\0';
  1140.     p = path2 + strlen(path2) - 2;
  1141.     if (p >= path2 && p[0] == '/' && p[1] == '.')
  1142.     p[0] = '\0';
  1143.     if (stat(path2, &st) == -1) {
  1144.     /* Either the directory does not exist, or it is a regexp
  1145.      * file name. Strip of the last component.
  1146.      */
  1147.     p = strrchr(path2, '/');
  1148.     if (p == 0 || p[1] == '\0')
  1149.         return 0;
  1150.     strncpy(rgexp, p+1, sizeof rgexp);
  1151.     rgexp[sizeof rgexp - 1] = '\0';
  1152.     *p = '\0';
  1153.     do_match = 1;
  1154.     }
  1155.     if (do_match && interactive)
  1156.     {
  1157.        dirp = opendir(path2);
  1158.        if (dirp == 0) {
  1159.            add_message("No such directory '%s'\n", path2);
  1160.            return 0;
  1161.        }
  1162.        (void)strcat(path2, "/");
  1163.        if (strcmp(path2, "obj/") == 0) danger = 1;
  1164.        for(de = readdir(dirp); de; de = readdir(dirp)) {
  1165.              if (!match_string(rgexp, de->d_name))
  1166.            continue;
  1167.            if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
  1168.            continue;
  1169.            if (strcmp(rgexp, "*") == 0 && de->d_name[0] == '.')
  1170.            continue;
  1171.        found = 1;
  1172.            if (danger && match_illegal(de->d_name))
  1173.        {
  1174.                add_message("Failed to remove: %s\n", de->d_name);
  1175.            continue;
  1176.            }
  1177.            (void)strcpy(temp, path2);
  1178.            (void)strcat(temp, de->d_name);
  1179.        (void)strcat(temp, "\0");
  1180.            if (unlink(temp) == -1)
  1181.                add_message("Failed to remove: %s\n", temp);
  1182.     }
  1183.     if (!found) add_message("File(s) not found.\n");
  1184.         closedir(dirp);
  1185.     }
  1186.     else 
  1187.     {
  1188.        if (unlink(path) == -1) {
  1189.        if (interactive) {
  1190.         add_message("No such file: %s\n", path);
  1191.         return 0;
  1192.        }
  1193.        }
  1194.     }
  1195.     return 1;
  1196. }
  1197.  
  1198. static int match_illegal(file)
  1199. char *file;
  1200. {
  1201. /*
  1202.  * No write permission for these files 
  1203.  */
  1204.   if (strcmp(file, "player.c") == 0 ||
  1205.       strcmp(file, "living.c") == 0 ||
  1206.       strcmp(file, "living.h") == 0 ||
  1207.       strcmp(file, "creature.c") == 0 ||
  1208.       strcmp(file, "creature.h") == 0) return 1;
  1209.   return 0;
  1210. }
  1211.  
  1212. int all_cap(str)
  1213. char *str;
  1214. {
  1215.     int i;
  1216.     for (i = 0; i < strlen(str); str++, i++)
  1217.     if (*str < 'A' || *str > 'Z') return 0;
  1218.     return 1;
  1219. }
  1220.  
  1221. static void set_hard_invis(ob, n)
  1222. struct object *ob;
  1223. int n;
  1224.     if (ob != current_object || current_object != command_giver
  1225.       || !(ob->flags & O_ONCE_INTERACTIVE))
  1226.     error("Illegal use of set_hard_invis()\n");
  1227.     if (n)
  1228.     ob->flags |= O_HARD_INVIS;
  1229.     else
  1230.     ob->flags &= ~O_HARD_INVIS;
  1231. }
  1232.  
  1233. static void set_see_hinvis(ob, n)
  1234. struct object *ob;
  1235. int n;
  1236.     if (ob != current_object || current_object != command_giver
  1237.       || !(ob->flags & O_ONCE_INTERACTIVE))
  1238.     error("Illegal use of set_see_hinvis()\n");
  1239.     if (n)
  1240.     ob->flags |= O_CAN_SEE_HINVIS;
  1241.     else
  1242.     ob->flags &= ~O_CAN_SEE_HINVIS;
  1243. }
  1244.